﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;

using System.Net.Mail;
using System.Net;

using System.Security.Cryptography;

namespace Recon.Portal.Data
{
    public class Utils
    {
        //protective string variables
        static string _passPhrase = "just2Protect@ll", _saltValue = "w@ll4Safety", _initVector = "d@13CFSwri9e7H8k"; // must be 16 bytes

        internal static string GenerateRandomPassword()
        {
            //set of allowed characters
            string allowedChars = "abcdefghijklmnopqrstuvwxyz0123456789@$!%*ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            string pwd = string.Empty; //holds generated password
            Random rnd = new Random(); //used for random number generation

            //generate password of length 8
            for (int i = 0; i <= 7; i++)
            {
                //add next random character from the list of allowed characters.
                pwd += allowedChars.Substring(
                    rnd.Next(0, allowedChars.Length - 1)
                    , 1);

                //remove the added character from the list of allowed characters
                allowedChars.Replace(pwd.Substring(pwd.Length - 1, 1), string.Empty);
            }

            //return the newly generated password
            return pwd;
        }

        internal static void sendEmail(string body, string subject, string to)
        {
            MailMessage mailMsg = new MailMessage();
            try
            {
                mailMsg.From = new MailAddress("mapp123.world@4circlesolutions.com");
                mailMsg.To.Add(to);
                mailMsg.Subject = subject;
                mailMsg.IsBodyHtml = true;
                mailMsg.BodyEncoding = Encoding.UTF8;
                mailMsg.Body = body;
                mailMsg.Priority = MailPriority.Normal;
                SmtpClient client = new SmtpClient();
                client.UseDefaultCredentials = false;
                client.Credentials = new NetworkCredential("mapp123.world@4circlesolutions.com", "radhe123");
                client.Host = "4circlesolutions.com";
                client.Port = 587;
                client.EnableSsl = false;
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Send(mailMsg);
            }
            catch (Exception exc)
            {
                if (exc != null)
                {
                    throw;
                }
            }
            finally
            {
                mailMsg = null;
            }
        }

        internal static string EncryptValue(string clearText)
        {
            // declare stream objectss
            MemoryStream memoryStream = null; // holds encrypted data.
            CryptoStream cryptoStream = null; // cryptographic stream for encryption
            string cipherText = string.Empty; //string to return

            try
            {
                // Convert plaintext into a byte array.
                byte[] clearTextBytes = Encoding.UTF8.GetBytes(clearText);

                // Convert initialization vector and salt value strings into byte arrays.
                byte[] initVectorBytes = Encoding.ASCII.GetBytes(_initVector);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(_saltValue);

                // Create a password from which the key will be derived, using the specified passphrase and salt value using the specified hash algorithm in 2 iterations.
                PasswordDeriveBytes password = new PasswordDeriveBytes(_passPhrase, saltValueBytes, "SHA1", 2);

                // Use the password to generate pseudo-random bytes for the encryption key, size of the key in bytes (instead of bits).
                byte[] keyBytes = password.GetBytes(32);

                // Create Rijndael encryption object, set encryption mode to Cipher Block Chaining (CBC)and use default options for other symmetric key parameters.
                RijndaelManaged symmetricKey = new RijndaelManaged();
                symmetricKey.Mode = CipherMode.CBC;

                // Define cryptographic stream - Write mode for encryption, encryptor from the existing key bytes and initialization vector and  Key size based on the number of key bytes.
                memoryStream = new MemoryStream();
                cryptoStream = new CryptoStream(memoryStream, symmetricKey.CreateEncryptor(keyBytes, initVectorBytes), CryptoStreamMode.Write);

                // encrypt till final block.
                cryptoStream.Write(clearTextBytes, 0, clearTextBytes.Length);
                cryptoStream.FlushFinalBlock();

                // Convert encrypted data from memory stream into a byte array and store in base 64 string to return.
                cipherText = Convert.ToBase64String(memoryStream.ToArray());
            }
            catch (Exception exc)
            {
                if (exc != null)
                {
                    throw;
                }
            }
            finally
            {
                // Close streams.
                if (memoryStream != null)
                {
                    memoryStream.Close();
                }
                if (cryptoStream != null)
                {
                    cryptoStream.Close();
                }
            }

            // Return encrypted string.
            return cipherText;
        }

        internal static string DecryptValue(string cipherText)
        {
            // declare stream objectss
            MemoryStream memoryStream = null; // holds encrypted data.
            CryptoStream cryptoStream = null; // cryptographic stream for encryption
            string clearText = string.Empty; //string to return

            try
            {
                // Convert ciphertext into a byte array.
                byte[] cipherTextBytes = Convert.FromBase64String(cipherText);

                // Convert initialization vector and salt value strings into byte arrays.
                byte[] initVectorBytes = Encoding.ASCII.GetBytes(_initVector);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(_saltValue);

                // Create a password from which the key will be derived, from the specified passphrase and salt value using the specified hash algorithm in 2 iterations.
                PasswordDeriveBytes password = new PasswordDeriveBytes(_passPhrase, saltValueBytes, "SHA1", 2);

                // Use the password to generate pseudo-random bytes for the encryption key, size of the key in bytes (instead of bits).
                byte[] keyBytes = password.GetBytes(32);

                // Create Rijndael encryption object, set encryption mode to Cipher Block Chaining (CBC)and use default options for other symmetric key parameters.
                RijndaelManaged symmetricKey = new RijndaelManaged();
                symmetricKey.Mode = CipherMode.CBC;

                // Define cryptographic stream - read mode for decryption, encryptor from the existing key bytes and initialization vector and  Key size based on the number of key bytes.
                memoryStream = new MemoryStream(cipherTextBytes);
                cryptoStream = new CryptoStream(memoryStream, symmetricKey.CreateDecryptor(keyBytes, initVectorBytes), CryptoStreamMode.Read);

                // allocate buffer long enough to hold ciphertext - plaintext is never longer than ciphertext.
                byte[] plainTextBytes = new byte[cipherTextBytes.Length];

                // Start decrypting.
                int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                // Convert decrypted data from memory stream into base 64 string to return.
                clearText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
            }
            catch (Exception exc)
            {
                if (exc != null)
                {
                    throw;
                }
            }
            finally
            {
                // Close streams.
                if (memoryStream != null)
                {
                    memoryStream.Close();
                }
                if (cryptoStream != null)
                {
                    cryptoStream.Close();
                }
            }

            // Return decrypted data converted into string.   
            return clearText;
        }

    }
}